﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Castle.Windsor;
using SuppKids.Controls;
using SuppKids.Core;
using SuppKids.Core.Domain;
using SuppKids.Core.Services;
using SuppKids.Resources;
using SuppKids.ViewModels;
using SuppKids.Core.Reporting;
using SuppKids.Core.Reporting.Data;
using Microsoft.Win32;
using System.IO;

namespace SuppKids
{
	/// <summary>
	/// Interaction logic for MenuRaskladka.xaml
	/// </summary>
	public partial class MenuRaskladkaEditor : BaseWindow
	{
		private readonly DailyMenuService dailyMenuService;
		private readonly DishService dishService;
		private readonly IngredientService ingredientService;
		private readonly ProductService productService;
		private readonly ProductConsumptionValueService productConsumptionValueService;
		private readonly GroupService groupService;
		private readonly DishAmountService dishAmountService;
        private readonly ReportGeneratorFactory reportGeneratorFactory;

		public MenuRaskladkaEditor(IWindsorContainer container, LicenseService licenseService, 
            DailyMenuService dailyMenuService, DishService dishService, IngredientService ingredientService, 
            ProductService productService, ProductConsumptionValueService productConsumptionValueService,
            GroupService groupService, DishAmountService dishAmountService, ReportGeneratorFactory reportGeneratorFactory)
			: base(container, licenseService)
		{
			this.dailyMenuService = dailyMenuService;
			this.dishService = dishService;
			this.ingredientService = ingredientService;
			this.productService = productService;
			this.productConsumptionValueService = productConsumptionValueService;
			this.groupService = groupService;
			this.dishAmountService = dishAmountService;
            this.reportGeneratorFactory = reportGeneratorFactory;

			InitializeComponent();

			this.AllDishesList.SelectedValuePath = Lambda.Property<Dish>(a => a.Id);
			this.AllDishesList.DisplayMemberPath = Lambda.Property<Dish>(a => a.Name);
			this.AllProductsList.SelectedValuePath = Lambda.Property<Product>(a => a.Id);
			this.AllProductsList.DisplayMemberPath = Lambda.Property<Product>(a => a.Name);

			this.AllDishesList.ItemsSource = dishService.GetAll().OrderBy(a => a.Name).ToArray();
			this.AllProductsList.ItemsSource = productService.GetAll().OrderBy(a => a.Name).ToArray();

			this.Filter.OnFilterChanged += OnFilterChanged;
		}

		public IEnumerable<Group> Groups
		{
			get
			{
				var items = this.groupService.GetAll();
				return items;
			}
		}

		public DailyMenu SelectedDailyMenu { get; set; }

		public Dish SelectedDish
		{
			get
			{
				return this.DishesList.SelectedItem as Dish;
			}
		}

		private void OnFilterChanged(object sender, Filter.FilterEventArgs e)
		{
			this.DishesList.Items.Clear();
			var dailyMenu = this.dailyMenuService.GetDailyMenu(e.FilterData.DayOfWeek, e.FilterData.WeekNumber, e.FilterData.MenuType, e.FilterData.MealType);
			if (dailyMenu == null)
			{
				dailyMenu = new DailyMenu
				{
					DayOfWeek = e.FilterData.DayOfWeek,
					WeekNumber = e.FilterData.WeekNumber,
					MenuType = e.FilterData.MenuType,
					MealType = e.FilterData.MealType,
				};
				this.dailyMenuService.RegisterSave(dailyMenu, true);
			}


			this.SelectedDailyMenu = dailyMenu;

			var dishes = SelectedDailyMenu.Dishes.OrderBy(a => a.Name);
			foreach (var dish in dishes)
			{
				this.DishesList.Items.Add(dish);
			}
		}

		private void DishesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.IngredientsList.Items.Clear();
			if (this.DishesList.SelectedItem == null)
			{
				this.IngredientsList.ItemsSource = null;
				this.IngredientsList.SelectedItem = null;
				return;
			}

			var dish = (Dish)this.DishesList.SelectedItem;
			var items = dish.Ingredients.OrderBy(a => a.Product.Name).ToArray();
			foreach (var item in items)
			{
				this.IngredientsList.Items.Add(item);
			}

			var dishAmounts = new List<DishAmount>();
			foreach (var @group in this.Groups)
			{
				var amount = dish.DishAmounts.FirstOrDefault(a => a.Group.Id == @group.Id && a.DailyMenu.Id == this.SelectedDailyMenu.Id) ?? new DishAmount(group, this.SelectedDailyMenu);

				if (amount.IsTransient)
				{
					dish.DishAmounts.Add(amount);
					this.dishService.RegisterSave(dish, true);
				}

				dishAmounts.Add(amount);
			}

			this.DishAmountsList.SetBinding(DataGrid.ItemsSourceProperty, new Binding { Source = dishAmounts });
		}

		private void AddDishButtonClick(object sender, RoutedEventArgs e)
		{
			if (this.SelectedDailyMenu != null)
			{
				this.DishSelectionPopup.Visibility = Visibility.Visible;
			}
			else
			{
				MessageBox.Show(Messages.DailyMenuIsNotSelected);
			}
		}

		private void RemoveDishButtonClick(object sender, RoutedEventArgs e)
		{
			var selectedItem = this.DishesList.SelectedItem;

			if (selectedItem == null)
			{
				MessageBox.Show(Messages.DishIsNotSelected);
				return;
			}

			var dish = (Dish)selectedItem;

			this.SelectedDailyMenu.Dishes.Remove(dish);
			this.dailyMenuService.SaveChanges();

			this.DishesList.Items.Remove(selectedItem);

		}

		private void AddProductButtonClick(object sender, RoutedEventArgs e)
		{
			if (this.Filter.IsFilled)
			{
				this.ProductSelectionPopup.Visibility = Visibility.Visible;
			}
			else
			{
				MessageBox.Show(Messages.DishIsNotSelected);
			}

		}

		private void RemoveProductButtonClick(object sender, RoutedEventArgs e)
		{
			var selectedItem = this.IngredientsList.SelectedItem;

			if (selectedItem == null)
			{
				MessageBox.Show(Messages.ProductIsNotSelected);
				return;
			}

			var ingredient = (Ingredient)selectedItem;

			this.ingredientService.RegisterDelete(ingredient, true);

			this.IngredientsList.Items.Remove(selectedItem);
		}

		private void AllDishesList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.DishSelectionPopup.Visibility = Visibility.Collapsed;

			var selectedDish = this.AllDishesList.SelectedItem as Dish;

			if (selectedDish == null)
			{
				return;
			}

			if (this.SelectedDailyMenu == null)
			{
				MessageBox.Show(Messages.DailyMenuIsNotSelected);
				return;
			}

			if (this.SelectedDailyMenu.Dishes.Any(a => a.Id == selectedDish.Id))
			{
				MessageBox.Show(Messages.DishIsAlreadyAdded);
				return;
			}

			this.SelectedDailyMenu.Dishes.Add(selectedDish);
			this.dailyMenuService.RegisterSave(this.SelectedDailyMenu, true);
			this.DishesList.Items.Add(selectedDish);

			this.AllDishesList.SelectedItem = null;
		}

		private void AllProductsList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			this.ProductSelectionPopup.Visibility = Visibility.Collapsed;

			var product = this.AllProductsList.SelectedItem as Product;

			if (product == null)
			{
				return;
			}

			if (this.SelectedDailyMenu == null)
			{
				MessageBox.Show(Messages.DailyMenuIsNotSelected);
				return;
			}

			if (this.SelectedDish == null)
			{
				MessageBox.Show(Messages.DishIsNotSelected);
				return;
			}

			if (this.SelectedDish.Ingredients.Any(a => a.Product.Id == product.Id))
			{
				MessageBox.Show(Messages.DishIsAlreadyAdded);
				return;
			}

			var ingredient = new Ingredient
			{
				Product = product,
				Dish = this.SelectedDish
			};

			this.ingredientService.RegisterSave(ingredient, true);
			this.IngredientsList.Items.Add(ingredient);

			this.AllProductsList.SelectedItem = null;
		}

		private void ProductConsumptionsList_OnCurrentCellChanged(object sender, EventArgs e)
		{
			this.productConsumptionValueService.SaveChanges();
		}

		private void IngredientsList_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			if (this.IngredientsList.SelectedItem == null)
			{
				this.ProductConsumptionsList.ItemsSource = null;
				this.ProductConsumptionsList.SelectedItem = null;
				return;
			}

			var ingredient = (Ingredient)this.IngredientsList.SelectedItem;

			var items = new List<ProductConsumptionValue>();
			foreach (var @group in this.Groups)
			{
				var consumptionValue = ingredient.ConsumptionValues.FirstOrDefault(a => a.Group.Id == @group.Id && a.DailyMenu.Id == this.SelectedDailyMenu.Id) ?? new ProductConsumptionValue(@group, this.SelectedDailyMenu);

				if (consumptionValue.IsTransient)
				{
					ingredient.ConsumptionValues.Add(consumptionValue);
					this.ingredientService.RegisterSave(ingredient, true);
				}
				items.Add(consumptionValue);
			}

			this.ProductConsumptionsList.SetBinding(DataGrid.ItemsSourceProperty, new Binding{Source = items});
		}

		private void DishAmountsList_OnCurrentCellChanged(object sender, EventArgs e)
		{
			this.dishAmountService.SaveChanges();
		}

		private void ReturnProductButtonClick(object sender, EventArgs e)
		{
            var saveFile = new SaveFileDialog
            {
                FileName = "Возврат продуктов.xlsx",
                DefaultExt = ".xlsx",
                Filter = "Excel files (.xlsx)|*.xlsx"
            };

            if (saveFile.ShowDialog() == true)
            {
                Stream stream = null;
                try
                {
                    stream = saveFile.OpenFile();
                    var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.ReturnProduct, ReportFormat.Excel);
                    reportGenerator.GenerateReport(null, stream);
                }
                catch (Exception)
                {
                    MessageBox.Show(Messages.SaveFileError);
                }
                finally
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }
                }
            }
		}
	}
}
